package com.zmn.oms.zmn.business.impl.work;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.engineer.common.dro.foreign.engineer.ForeignEngineerDetailInfoDRO;
import com.zmn.base.engineer.dubbo.interfaces.foreign.EngineerListRemoteService;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.math.MoneyUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.oms.business.interfaces.messageV1.common.MessageSendBaseService;
import com.zmn.oms.business.interfaces.work.tag.OrderTagBService;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.DateTimeUtil;
import com.zmn.oms.common.utils.MobileUtil;
import com.zmn.oms.common.vo.KVDict;
import com.zmn.oms.constant.MessageQueueTopicConstant;
import com.zmn.oms.manager.utils.OmsMqTagConsts;
import com.zmn.oms.model.dto.messageV1.AppMessageDTO;
import com.zmn.oms.model.dto.acceptance.OrderWorkAcceptanceDTO;
import com.zmn.oms.model.dto.tag.OrderTagAddDTO;
import com.zmn.oms.model.dto.visit.OrderVisitDTO;
import com.zmn.oms.model.dto.work.modify.OrderMultipleVisitDTO;
import com.zmn.oms.model.dto.work.orderpay.CancelPayDTO;
import com.zmn.oms.model.entity.conf.cancel.OrderCancelReasonQuery;
import com.zmn.oms.model.entity.orderattachment.OrderAttachment;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.tag.OrderTag;
import com.zmn.oms.model.entity.visit.OrderVisit;
import com.zmn.oms.model.entity.visit.OrderVisitQuery;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.vo.conf.cancel.OrderCancelReasonVO;
import com.zmn.oms.model.vo.visit.CancelMultipleVisitVO;
import com.zmn.oms.services.interfaces.conf.cancel.OrderCancelReasonService;
import com.zmn.oms.services.interfaces.orderattachment.OrderAttachmentService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.tag.OrderTagService;
import com.zmn.oms.services.interfaces.visit.OrderVisitService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.business.interfaces.acceptance.OrderWorkAcceptanceBService;
import com.zmn.oms.zmn.business.interfaces.work.OrderWorkMultipleVisitBService;
import com.zmn.pay.common.constant.PayConsts;
import io.shardingsphere.core.keygen.DefaultKeyGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 类描述：多次上门
 *
 * @author yule
 * @date 2021/3/11 18:33
 */
@Slf4j
@Service
public class OrderWorkMultipleVisitBServiceImpl implements OrderWorkMultipleVisitBService {

    @Autowired
    private OrderVisitService orderVisitService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderTagBService orderTagBService;
    @Autowired
    private OrderPayService orderPayService;
    @Autowired
    DefaultKeyGenerator defaultKeyGenerator;
    @Autowired
    private OrderWorkAcceptanceBService orderWorkAcceptanceBService;
    @Autowired
    private MessageSendBaseService messageSendBaseService;
    @Autowired
    private OrderAttachmentService orderAttachmentService;

    @Resource
    private ZmnMQSender zmnMQSender;

    @Resource
    OrderCancelReasonService orderCancelReasonService;
    @Reference(version = com.zmn.base.engineer.common.constants.DubboConsts.INTERFACE_VERSION, check = false)
    EngineerListRemoteService engineerListRemoteService;

    /**
     * 申请多次上门
     */
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_APPLY_MULTIPLE_VISIT, beforeProceed = false)
    @Override
    public OrderVisitDTO addOrderMultipleVisit(OrderMultipleVisitDTO orderMultipleVisitDTO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findMasterWorkDetail(orderMultipleVisitDTO.getOrderId(),
                orderMultipleVisitDTO.getWorkId(), orderMultipleVisitDTO.getMasterId());
        if (NumberUtil.isNotNullOrZero(orderMultipleVisitDTO.getAmount())) {
            if (orderMultipleVisitDTO.getAmount() >= orderWork.getMasterAmount()) {
                throw new OmsBaseException("输入金额不得大于等于" + MoneyUtil.parseToYuanStr(orderWork.getMasterAmount()));
            }
        }
        this.checkOrderStatus(orderWork);

        List<OrderVisit> dbOrderVisitList = orderVisitService.listByOrderIdAndMasterIdSrcMaster(orderWork.getOrderId(), orderWork.getMasterId());
        if (CollectionUtil.isNotNullOrEmpty(dbOrderVisitList)) {
            OrderVisit orderVisit = dbOrderVisitList.get(dbOrderVisitList.size() - 1);
            if (Objects.equals(orderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY) ||
                    Objects.equals(orderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_SET_OUT)) {
                throw new OmsBaseException("已存在再次上门申请，不可操作");
            }
        }

        long orderPayId = 0L;
        if (NumberUtil.isNotNullOrZero(orderMultipleVisitDTO.getAmount())) {
            // 先插入待支付记录
            OrderPay orderPay = new OrderPay();
            orderPay.setOrderPayId(defaultKeyGenerator.generateKey().longValue());
            orderPay.setOrderId(orderWork.getOrderId());
            orderPay.setWorkId(orderWork.getWorkId());
            orderPay.setAmountType(orderMultipleVisitDTO.getAmountType());
            orderPay.setAmount(orderMultipleVisitDTO.getAmount());
            orderPay.setTradeType(PayConsts.PAY_TRADE_TYPE_INTIME);
            orderPay.setPayStatus(PayConsts.PAY_STATUS_NONE);
            orderPay.setPayChannelId(0);
            orderPay.setCreater(orderMultipleVisitDTO.getOperator());
            orderPay.setUpdater(orderMultipleVisitDTO.getOperator());
            orderPay.setCreateTime(orderMultipleVisitDTO.getOperateTime());
            orderPay.setUpdateTime(orderMultipleVisitDTO.getOperateTime());
            orderPayService.insertOrderPay(orderPay);
            orderPayId = orderPay.getOrderPayId();
        }

        OrderVisitDTO returnDTO = new OrderVisitDTO();
        returnDTO.setOrderPayId(orderPayId);

        String masterName = orderWork.getMasterName();
        // 查询工程师信息
        ResponseDTO<ForeignEngineerDetailInfoDRO> cacheEngineerByEngineerId = engineerListRemoteService
                .getEngineerDetailById(orderWork.getMasterId());
        ForeignEngineerDetailInfoDRO baseEngineerDRO = cacheEngineerByEngineerId.getData();
        if (cacheEngineerByEngineerId.isSuccess() && Objects.nonNull(cacheEngineerByEngineerId.getData())) {
            masterName += "-" + MobileUtil.formatHideTel(baseEngineerDRO.getMobile());
        }

        // 保存上门信息
        OrderVisit orderVisit = new OrderVisit();
        orderVisit.setOrderId(orderMultipleVisitDTO.getOrderId());
        orderVisit.setMasterId(orderWork.getMasterId());
        orderVisit.setMasterName(masterName);
        orderVisit.setOrderPayId(orderPayId);
        orderVisit.setAmount(Optional.ofNullable(orderMultipleVisitDTO.getAmount()).orElse(0));
        orderVisit.setAmountType(orderMultipleVisitDTO.getAmountType());
        orderVisit.setPayStatus(PayConsts.PAY_STATUS_NONE);
        orderVisit.setVisitType(orderMultipleVisitDTO.getVisitType());
        orderVisit.setVisitStatus(OrderVisitStatusConsts.ORDER_VISIT_STATUS_APPLY);
        orderVisit.setExpectVisitTime(orderMultipleVisitDTO.getExpectVisitTime());

        // 保存到附件表
        if (StringUtil.isNotBlank(orderMultipleVisitDTO.getImgSrc())) {
            String[] msg = orderMultipleVisitDTO.getImgSrc().split(",");
            StringJoiner sj = new StringJoiner(",");
            for (String str : msg) {
                OrderAttachment attachment = new OrderAttachment();
                attachment.setOrderId(orderWork.getOrderId());
                attachment.setType(OrderVisitStatusConsts.ORDER_ATTACHMENT_TYPE);
                attachment.setSrc(str);
                attachment.setNeedReview(GlobalConsts.NO);
                attachment.setCreater(orderMultipleVisitDTO.getOperator());
                orderAttachmentService.insertAttachment(attachment);
                sj.add(String.valueOf(attachment.getAttachmentId()));
            }
            orderVisit.setAttachmentIds(sj.toString());
        }
        orderVisit.setRemark(orderMultipleVisitDTO.getRemark());
        orderVisit.setCreater(orderMultipleVisitDTO.getOperator());
        orderVisit.setUpdater(orderMultipleVisitDTO.getOperator());
        orderVisit.setCreateTime(orderMultipleVisitDTO.getOperateTime());
        orderVisit.setUpdateTime(orderMultipleVisitDTO.getOperateTime());
        orderVisitService.insertOrderVisit(orderVisit);
        returnDTO.setVisitId(orderVisit.getVisitId());

        // 判断是否多次收款
        if (Objects.equals(orderMultipleVisitDTO.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_OTHER)) {
            OrderTagAddDTO tagAddDTO = new OrderTagAddDTO();
            tagAddDTO.setOrderId(orderWork.getOrderId());
            tagAddDTO.setWorkId(orderWork.getWorkId());
            tagAddDTO.setTagIdList(Lists.newArrayList(OrderTagConsts.TAG_ID_HIGH_MULTIPLE_VISIT));
            orderTagBService.addOrderTag(tagAddDTO);
            // 多次收款标签
            /*Integer count = orderTagService.countOrderTagByOrderIdAndTagIdSrcMaster(orderWork.getOrderId(), OrderTagConsts.TAG_ID_HIGH_MULTIPLE_VISIT);
            if (count == 0) {
                OrderTag orderTag = new OrderTag();
                orderTag.setOrderId(orderWork.getOrderId());
                orderTag.setWorkId(orderWork.getWorkId());
                orderTag.setTagType(OrderTagConsts.ORDER_TAG_USER_STAFF);
                orderTag.setTagId(OrderTagConsts.TAG_ID_HIGH_MULTIPLE_VISIT);
                orderTag.setTagName(OrderTagConsts.getTagName(OrderTagConsts.TAG_ID_HIGH_MULTIPLE_VISIT));
                orderTag.setCreater(orderMultipleVisitDTO.getOperator());
                orderTag.setUpdater(orderMultipleVisitDTO.getOperator());
                orderTagService.insertOrderTag(orderTag);
            }*/
        } else {
            OrderWork updateOrderWork = new OrderWork();
            updateOrderWork.setOrderId(orderMultipleVisitDTO.getOrderId());
            updateOrderWork.setWorkId(orderMultipleVisitDTO.getWorkId());
            if (Objects.equals(orderMultipleVisitDTO.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_DELIVERY)) {
                updateOrderWork.setDelivery(GlobalConsts.YES);
            } else {
                updateOrderWork.setWaitPart(GlobalConsts.YES);
            }
            updateOrderWork.setUpdater(orderMultipleVisitDTO.getOperator());
            orderWorkService.updateOrderWorkByKey(updateOrderWork);
        }

        // 运营后台添加多次上门发送通知消息
        if (Objects.equals(orderMultipleVisitDTO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_STAFF)) {
            Map<String, Object> params = Maps.newHashMap();
            params.put("order_id", String.valueOf(orderWork.getOrderId()));
            params.put("work_id", String.valueOf(orderWork.getWorkId()));
            params.put("time", DateUtil.dateFormatToString(orderMultipleVisitDTO.getExpectVisitTime(), DateUtil.FORMAT_DEFAULT));

            AppMessageDTO appMessageDTO = new AppMessageDTO();
            appMessageDTO.setOrderId(orderWork.getOrderId());
            appMessageDTO.setChannelId(String.valueOf(orderWork.getChannelId()));
            appMessageDTO.setCityId(String.valueOf(orderWork.getCityId()));
            appMessageDTO.setPlat(orderWork.getPlatWork());
            appMessageDTO.setMasterId(orderWork.getMasterId());
            appMessageDTO.setRuleId(MessageConsts.APP_PUSH_MSG_RULE_ID_MULTIPLE_VISIT);
            appMessageDTO.setParams(JSON.toJSONString(params));
            log.info("[{}]验收结果发送app消息-开始", orderWork.getOrderId());
            Boolean isSuccess = messageSendBaseService.sendAndroidAndIOSMessage(appMessageDTO);
            log.info("[{}]验收结果发送app消息结果：【{}】-结束", orderWork.getOrderId(), isSuccess);
        }

        // 多次上门预警提醒
        this.sendMultipleVisitRemind(orderVisit);

        return returnDTO;
    }

    /**
     * 发送再次上门提醒
     * 下次上门当天8点/前一天8点，向工程师发送预警消息
     * @param orderVisit
     */
    private void sendMultipleVisitRemind(OrderVisit orderVisit) {
        OrderVisit messageVisit = new OrderVisit();
        messageVisit.setVisitId(orderVisit.getVisitId());
        messageVisit.setOrderId(orderVisit.getOrderId());
        messageVisit.setExpectVisitTime(orderVisit.getExpectVisitTime());

        Date sendDate = DateTimeUtil.getStartDeliverTime(DateUtil.getNow(), orderVisit.getExpectVisitTime());
        if (Objects.isNull(sendDate)) {
            return;
        }

        long time = sendDate.getTime();
        String message = JSON.toJSONString(messageVisit);
        String key = String.format("%s-multiple-visit", orderVisit.getOrderId());
        log.info("多次上门预警消息：key:{}，message:{}，下次判断时间：{}，预计下次上门时间：{}", key, message,
                DateUtil.dateFormatToString(sendDate, DateUtil.FORMAT_DEFAULT),
                DateUtil.dateFormatToString(orderVisit.getExpectVisitTime(), DateUtil.FORMAT_DEFAULT));
        zmnMQSender.sendWithStartDeliverTime(MessageQueueTopicConstant.ZMN_TOPIC_OMS, OmsMqTagConsts.MULTIPLE_VISIT_WARNING_TAG, key, message, time);
    }

    /**
     * 检查订单状态
     * @param orderWork
     */
    private void checkOrderStatus(OrderWork orderWork) throws OmsBaseException {
        if (orderWork == null) {
            throw new OmsBaseException(OrderFailConsts.FAIL_DATA_CHANGE_ORDER_NOMASTER,"无效的工单");
        }

        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            throw new OmsBaseException("工单不在进行中");
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_AGAIN_SET_OUT, beforeProceed = false)
    @Override
    public void againSetOut(OrderMultipleVisitDTO orderMultipleVisitDTO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findMasterWorkDetail(orderMultipleVisitDTO.getOrderId(),
                orderMultipleVisitDTO.getWorkId(), orderMultipleVisitDTO.getMasterId());
        this.checkOrderStatus(orderWork);

        OrderVisitQuery query = new OrderVisitQuery();
        query.setOrderId(orderMultipleVisitDTO.getOrderId());
        query.setVisitId(orderMultipleVisitDTO.getVisitId());
        OrderVisit dbOrderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(query);
        if (Objects.equals(dbOrderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL)) {
            throw new OmsBaseException("本次上门已取消");
        }

        OrderVisit orderVisit = new OrderVisit();
        orderVisit.setVisitId(orderMultipleVisitDTO.getVisitId());
        orderVisit.setOrderId(orderMultipleVisitDTO.getOrderId());
        orderVisit.setVisitStatus(OrderVisitStatusConsts.ORDER_VISIT_STATUS_SET_OUT);
        orderVisit.setSetOutTime(orderMultipleVisitDTO.getOperateTime());
        orderVisit.setUpdater(orderMultipleVisitDTO.getOperator());
        orderVisit.setUpdateTime(orderMultipleVisitDTO.getOperateTime());
        orderVisitService.updateByKey(orderVisit);
    }

    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_AGAIN_VISIT, beforeProceed = false)
    @Override
    public void againVisit(OrderMultipleVisitDTO orderMultipleVisitDTO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findMasterWorkDetail(orderMultipleVisitDTO.getOrderId(),
                orderMultipleVisitDTO.getWorkId(), orderMultipleVisitDTO.getMasterId());
        this.checkOrderStatus(orderWork);

        OrderVisitQuery query = new OrderVisitQuery();
        query.setOrderId(orderMultipleVisitDTO.getOrderId());
        query.setVisitId(orderMultipleVisitDTO.getVisitId());
        OrderVisit dbOrderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(query);
        orderMultipleVisitDTO.setDbOrderVisit(dbOrderVisit);
        if (Objects.equals(dbOrderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL)) {
            throw new OmsBaseException("本次上门已取消");
        }

        // 下次上门2小时前不可上门
//        Date before = DateUtil.getBaseDefer(dbOrderVisit.getExpectVisitTime(),0,0,0,-2,0, 0);
//        if (DateUtil.getNow().getTime() < before.getTime()) {
//            throw new OmsBaseException("请在" + DateUtil.toString(before, "HH时mm分") + " ~ " + DateUtil.toString(dbOrderVisit.getExpectVisitTime(), "HH时mm分") + "上门 ");
//        }

        OrderVisit orderVisit = new OrderVisit();
        orderVisit.setVisitId(orderMultipleVisitDTO.getVisitId());
        orderVisit.setOrderId(orderMultipleVisitDTO.getOrderId());
        orderVisit.setVisitStatus(OrderVisitStatusConsts.ORDER_VISIT_STATUS_VISIT);
        orderVisit.setActualVisitTime(orderMultipleVisitDTO.getOperateTime());
        orderVisit.setUpdater(orderMultipleVisitDTO.getOperator());
        orderVisit.setUpdateTime(orderMultipleVisitDTO.getOperateTime());
        orderVisitService.updateByKey(orderVisit);
    }

    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_CANCEL_AGAIN_VISIT, beforeProceed = false)
    @Override
    public void cancelAgainVisit(OrderMultipleVisitDTO orderMultipleVisitDTO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderMultipleVisitDTO.getOrderId(),
                orderMultipleVisitDTO.getWorkId());
        this.checkOrderStatus(orderWork);

        this.processCancelVisit(orderMultipleVisitDTO, orderWork);
    }

    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_ENGINEER_CANCEL_AGAIN_VISIT, beforeProceed = false)
    @Override
    public void engineerCancelAgainVisit(OrderMultipleVisitDTO orderMultipleVisitDTO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findMasterWorkDetail(orderMultipleVisitDTO.getOrderId(),
                orderMultipleVisitDTO.getWorkId(), orderMultipleVisitDTO.getMasterId());
        this.checkOrderStatus(orderWork);

        this.processCancelVisit(orderMultipleVisitDTO, orderWork);
    }

    /**
     * 取消再次上门
     * @param orderMultipleVisitDTO
     * @param orderWork
     */
    private void processCancelVisit(OrderMultipleVisitDTO orderMultipleVisitDTO, OrderWork orderWork) throws OmsBaseException {

        OrderVisitQuery query = new OrderVisitQuery();
        query.setOrderId(orderMultipleVisitDTO.getOrderId());
        query.setVisitId(orderMultipleVisitDTO.getVisitId());
        OrderVisit dbOrderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(query);
        orderMultipleVisitDTO.setDbOrderVisit(dbOrderVisit);
        if (Objects.equals(dbOrderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL)) {
            throw new OmsBaseException("本次上门已取消");
        }

        if (Objects.equals(orderMultipleVisitDTO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)) {
            if (NumberUtil.isNullOrZero(dbOrderVisit.getOrderPayId())) {
                if (Objects.equals(dbOrderVisit.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS)
                        || Objects.equals(dbOrderVisit.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_NON)
                        || NumberUtil.isNullOrZero(dbOrderVisit.getAcceptanceId())) {
                    throw new OmsBaseException("本次上门已确定，不可取消");
                }
            } else {
                if (Objects.equals(dbOrderVisit.getPayStatus(), PayConsts.PAY_STATUS_DONE)) {
                    throw new OmsBaseException("本次上门已支付，不可取消");
                }
            }
        }

        if (NumberUtil.isNotNullOrZero(dbOrderVisit.getAcceptanceId())
                && Objects.equals(dbOrderVisit.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_WAIT)) {
            // 取消上门，将上门发起的验收状态改为取消验收
            OrderWorkAcceptanceDTO dto = new OrderWorkAcceptanceDTO();
            dto.setOperator(orderMultipleVisitDTO.getOperator());
            dto.setOperatorId(orderMultipleVisitDTO.getOperatorId());
            dto.setOperatorType(orderMultipleVisitDTO.getOperatorType());
            dto.setOrderId(orderMultipleVisitDTO.getOrderId());
            dto.setWorkId(orderMultipleVisitDTO.getWorkId());
            dto.setAcceptanceId(dbOrderVisit.getAcceptanceId());
            dto.setAcceptanceResultStatus(OrderConsts.ORDER_ACCEPTANCE_STATUS_CANCEL);
            dto.setOperateTime(new Date(orderMultipleVisitDTO.getOperateTime().getTime() + 2));
            orderWorkAcceptanceBService.modifyOrderWorkAcceptance(dto);
        }

        // 如果是拉修/待件，则把主表拉修/待件标识去掉
        if (!Objects.equals(dbOrderVisit.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_OTHER)) {
            OrderWork updateWork = new OrderWork();
            updateWork.setOrderId(orderWork.getOrderId());
            updateWork.setWorkId(orderWork.getWorkId());
            if (Objects.equals(dbOrderVisit.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_DELIVERY)) {
                updateWork.setDelivery(GlobalConsts.NO);
            } else {
                updateWork.setWaitPart(GlobalConsts.NO);
            }
            updateWork.setUpdater(orderMultipleVisitDTO.getOperator());
            orderWorkService.updateOrderWorkByKey(updateWork);
        }

        // 取消本次上门
        OrderVisit orderVisit = new OrderVisit();
        orderVisit.setVisitId(orderMultipleVisitDTO.getVisitId());
        orderVisit.setOrderId(orderMultipleVisitDTO.getOrderId());
        orderVisit.setVisitStatus(OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL);
        // 组装取消缘由
        if (CollectionUtil.isNotNullOrEmpty(orderMultipleVisitDTO.getReasonIdList())) {
            StringJoiner idSj = new StringJoiner(",");
            orderMultipleVisitDTO.getReasonIdList().forEach(str -> idSj.add(str));
            StringJoiner vallueSj = new StringJoiner(",");
            orderMultipleVisitDTO.getReasonValueList().forEach(str -> vallueSj.add(str));
            orderVisit.setReasonIds(idSj.toString());
            orderVisit.setReasonValues(vallueSj.toString());
        }
        orderVisit.setUpdater(orderMultipleVisitDTO.getOperator());
        orderVisit.setUpdateTime(orderMultipleVisitDTO.getOperateTime());
        orderVisitService.updateByKey(orderVisit);

        // 如果未支付，则删除支付记录，否则不删除支付记录
        if (NumberUtil.isNotNullOrZero(dbOrderVisit.getOrderPayId()) && Objects.equals(dbOrderVisit.getPayStatus(), PayConsts.PAY_STATUS_NONE)) {
            // 删除支付记录
            CancelPayDTO cancelPayDTO = new CancelPayDTO();
            cancelPayDTO.setOrderPayId(dbOrderVisit.getOrderPayId());
            cancelPayDTO.setOrderId(orderMultipleVisitDTO.getOrderId());
            cancelPayDTO.setWorkId(orderMultipleVisitDTO.getWorkId());
            cancelPayDTO.setAmountType(dbOrderVisit.getAmountType());
            cancelPayDTO.setOperator(orderMultipleVisitDTO.getOperator());
            cancelPayDTO.setOperatorId(orderMultipleVisitDTO.getOperatorId());
            cancelPayDTO.setOperatorType(orderMultipleVisitDTO.getOperatorType());
            cancelPayDTO.setOperateTime(new Date(orderMultipleVisitDTO.getOperateTime().getTime() + 3));
            orderPayService.deleteByKeyRecordLog(cancelPayDTO);
        }
    }

    /**
     * 取消多次上门vo
     * @param orderWork
     * @return
     */
    @Override
    public CancelMultipleVisitVO getCancelMultipleVisitVO(OrderWork orderWork) {
        // 取消缘由（根据：服务平台、订单节点、类型：后台、状态：启用）
        List<KVDict<Integer>> cancelList = Lists.newArrayList();
        OrderCancelReasonQuery orderCancelReasonQuery = new OrderCancelReasonQuery();
        orderCancelReasonQuery.setBizType(orderWork.getBizType());
        orderCancelReasonQuery.setType(1);
        orderCancelReasonQuery.setStatus(GlobalConsts.YES);
        // 未派单取消：已录入/已确认/已分单-进行中
        List<Integer> undistributedList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_INPUT, OrderStatusConsts.WORK_STATUS_CONFIRM, OrderStatusConsts.WORK_STATUS_ASSIGN);
        // 未上门取消：已派单/已领单-进行中
        List<Integer> unvisitedList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE);
        // 已上门取消：已上门-进行中
        List<Integer> visitedList = Lists.newArrayList(OrderStatusConsts.WORK_STATUS_VISIT);
        Integer status = orderWork.getStatus();
        Integer resultStatus = orderWork.getResultStatus();
        Integer node = 0;
        // 取消节点 1 未派单取消、2 未上门取消、3 已上门取消
        if (Objects.equals(resultStatus, 1)) {
            if (undistributedList.contains(status)) {
                node = GlobalConsts.LEVEL_1;
            } else if (unvisitedList.contains(status)) {
                node = GlobalConsts.LEVEL_2;
            } else if (visitedList.contains(status)) {
                node = GlobalConsts.LEVEL_3;
            }
        }
        orderCancelReasonQuery.setNode(node);
        List<OrderCancelReasonVO> orderCancelReasonVOList = orderCancelReasonService.listByQuery(orderCancelReasonQuery);
        orderCancelReasonVOList.stream().sorted(Comparator.comparing(OrderCancelReasonVO::getId)).forEach(e -> cancelList.add(KVDict.<Integer>builder().value(e.getId()).text(e.getReason()).build()));
        CancelMultipleVisitVO vo = new CancelMultipleVisitVO();
        vo.setCancelList(cancelList);
        return vo;
    }

    /**
     * 处理多次上门预警
     * @param orderVisit
     */
    @Override
    public void processMultipleVisitWarning(OrderVisit orderVisit) {

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderVisit.getOrderId(), orderVisit.getOrderId());

        OrderVisitQuery query = new OrderVisitQuery();
        query.setOrderId(orderVisit.getOrderId());
        query.setVisitId(orderVisit.getVisitId());
        OrderVisit dbOrderVisit = orderVisitService.findOrderVisitByQuery(query);
        if (Objects.equals(dbOrderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_VISIT)
                || Objects.equals(dbOrderVisit.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL)) {
            return;
        }

        /**
         * 判断是否需要发送预警消息
         * 0代表当天上门需要发送
         * 1代表明天上门需要发送，重新进入队列，明天需要再次发送一次
         * 2代表明天以后上门不需要发送，重新进入队列
         */
        int status = DateTimeUtil.isSendWarn(DateUtil.getNow(), dbOrderVisit.getExpectVisitTime());
        if (status != 2) {
            Map<String, Object> params = Maps.newHashMap();
            params.put("order_id", String.valueOf(orderWork.getOrderId()));
            params.put("work_id", String.valueOf(orderWork.getWorkId()));
            params.put("time", DateUtil.dateFormatToString(dbOrderVisit.getExpectVisitTime(), DateUtil.FORMAT_DEFAULT));

            AppMessageDTO appMessageDTO = new AppMessageDTO();
            appMessageDTO.setOrderId(orderWork.getOrderId());
            appMessageDTO.setChannelId(String.valueOf(orderWork.getChannelId()));
            appMessageDTO.setCityId(String.valueOf(orderWork.getCityId()));
            appMessageDTO.setPlat(orderWork.getPlatWork());
            appMessageDTO.setMasterId(orderWork.getMasterId());
            appMessageDTO.setRuleId(MessageConsts.APP_PUSH_MSG_RULE_ID_AGAIN_VISIT_REMIND);
            appMessageDTO.setParams(JSON.toJSONString(params));
            log.info("[{}]再次上门提醒-开始", orderWork.getOrderId());
            Boolean isSuccess = messageSendBaseService.sendAndroidAndIOSMessage(appMessageDTO);
            log.info("[{}]再次上门提醒结果：【{}】-结束", orderWork.getOrderId(), isSuccess);
        }

        if (status != 0) {
            this.sendMultipleVisitRemind(dbOrderVisit);
        }
    }

    @Override
    public OrderVisitDTO getOrderVisitByQuery(OrderVisitQuery orderVisitQuery) {
        OrderVisit orderVisit = orderVisitService.findOrderVisitByQuerySrcMaster(orderVisitQuery);
        OrderVisitDTO orderVisitDTO = BeanMapper.map(orderVisit, OrderVisitDTO.class);
        if (StringUtil.isNotBlank(orderVisitDTO.getAttachmentIds())) {
            String[] ids = orderVisitDTO.getAttachmentIds().split(",");
            List<OrderAttachment> orderAttachmentList = orderAttachmentService.listAttachmentByOrderIdSrcMaster(orderVisitQuery.getOrderId());
            if (CollectionUtil.isNotNullOrEmpty(orderAttachmentList)) {
                Map<Long, OrderAttachment> map = orderAttachmentList.stream()
                        .collect(Collectors.toMap(OrderAttachment::getAttachmentId, orderAttachment -> orderAttachment));
                StringJoiner sj = new StringJoiner(",");
                for (String s : ids) {
                    OrderAttachment attachment = map.get(Long.valueOf(s));
                    if (Objects.nonNull(attachment)) {
                        sj.add(attachment.getSrc());
                    }
                }
                orderVisitDTO.setImgSrc(sj.toString());
            }
        }
        return orderVisitDTO;
    }

    @Override
    public List<OrderVisitDTO> listOrderVisitByOrderIdAndMasterId(Long orderId, Integer masterId) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, orderId);
        List<OrderVisit> orderVisitList = orderVisitService.listByOrderIdAndMasterIdSrcMaster(orderId, masterId);
        List<OrderVisitDTO> orderVisitDTOList = BeanMapper.mapList(orderVisitList, OrderVisitDTO.class);

        orderVisitDTOList = orderVisitDTOList.stream()
                .filter(e -> !Objects.equals(e.getVisitStatus(), OrderVisitStatusConsts.ORDER_VISIT_STATUS_CANCEL))
                .collect(Collectors.toList());

        List<OrderAttachment> orderAttachmentList = orderAttachmentService.listAttachmentByOrderIdSrcMaster(orderId);
        Map<Long, OrderAttachment> map = new HashMap<>();
        if (CollectionUtil.isNotNullOrEmpty(orderAttachmentList)) {
            map = orderAttachmentList.stream().collect(Collectors.toMap(OrderAttachment::getAttachmentId, orderAttachment -> orderAttachment));
        }

        for (int i = 0; i < orderVisitDTOList.size(); i++) {
            OrderVisitDTO dto = orderVisitDTOList.get(i);
            // 处理照片附件
            if (StringUtil.isNotBlank(dto.getAttachmentIds())) {
                String[] ids = dto.getAttachmentIds().split(",");
                StringJoiner sj = new StringJoiner(",");
                for (String s : ids) {
                    OrderAttachment attachment = map.get(Long.valueOf(s));
                    if (Objects.nonNull(attachment)) {
                        sj.add(attachment.getSrc());
                    }
                }
                dto.setImgSrc(sj.toString());
            }
            // 判断金额0的支付状态
            if (NumberUtil.isNullOrZero(dto.getOrderPayId())
                    && (Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_SUCCESS)
                    || Objects.equals(dto.getAcceptanceResultStatus(), OrderConsts.ORDER_ACCEPTANCE_STATUS_NON)
                    || NumberUtil.isNullOrZero(dto.getAcceptanceId()))) {
                dto.setPayStatus(PayConsts.PAY_STATUS_DONE);
            }
            // 处理标题
            if (Objects.equals(dto.getVisitType(), OrderVisitStatusConsts.ORDER_VISIT_TYPE_OTHER)) {
                dto.setTitle("第" + (i + 1) + "次收款");
            } else {
                dto.setTitle(OrderVisitStatusConsts.getVisitTypeName(dto.getVisitType()));
            }
        }

        orderVisitDTOList = orderVisitDTOList.stream().sorted(Comparator.comparing(OrderVisitDTO::getCreateTime).reversed()).collect(Collectors.toList());
        OrderVisitDTO firstVisit = new OrderVisitDTO();
        firstVisit.setTitle("首次上门");
        firstVisit.setOrderId(orderWork.getOrderId());
        firstVisit.setExpectVisitTime(orderWork.getVisitTime());
        orderVisitDTOList.add(firstVisit);
        return orderVisitDTOList;
    }

}
